package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.Dto.ArticleDto;
import com.heima.media.Dto.ContentDto;
import com.heima.media.Dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleFeign;
import com.heima.media.service.*;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class IAuditServiceImpl implements IAuditService {

    @Autowired
    GreenTextScan textScan;
    @Autowired
    GreenImageScan imageScan;
    @Autowired
    IWmNewsService wmNewsService;
    @Autowired
    ArticleFeign articleFeign;
    @Autowired
    IWmUserService userService;
    @Autowired
    IWmChannelService channelService;
    @Autowired
    MinIOService minIOService;
    @Autowired
    RedissonClient redissonClient;

    /*
        审核
    */
    @Async  //当前方法开启线程池
    @Override
    public void audit(WmNews wmNews) {
        System.err.println(Thread.currentThread().getName() + "开始执行审核。。。");

        //如果状态是 8(自动审核通过) 或者是4(人工审核通过) 开始进入发布状态
        if (wmNews.getStatus() == 8 || wmNews.getStatus() == 4){
            //判断是否到达发布时间
            if (wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
                publishArticle(wmNews);
            }else {
                //延时发布
                long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
                RBlockingQueue<Object> blockingQueue = redissonClient.getBlockingQueue("article_publish");
                RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
                delayedQueue.offer(wmNews.getId().toString(),time,TimeUnit.SECONDS);
                return;
            }
        }

        //判断文章状态  为1 时进入自动审核状态
        if (wmNews.getStatus() == 1){
            //分别提取文章的文本和图片
           Map<String,Object> map =  getTextAndImages(wmNews.getContent());
           //获取文本信息
           String text = (String) map.get("text");
           //获取图片信息
           List<String> images = (List<String>) map.get("images");

           //调用阿里审核之前 自管理敏感词审核
            boolean selfResult = checkSelf(wmNews,text);
            if (!selfResult) return;
            //审核文本内容
            boolean textResult = checkText(wmNews,text);
            if (!textResult) return;
            //审核图片内容
            //获取封面图片
            List<ImageDto> covers = JSON.parseArray(wmNews.getImages(),ImageDto.class);
            for (ImageDto cover : covers) {
                //判断封面图片在不在图片集合中
                if (images.contains(cover.getUrl())){
                    images.add(cover.getUrl());
                }
            }
            //审核图片内容
            boolean imagesResult =  checkImages(wmNews,images);
            if (!imagesResult) return;

            if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
                wmNews.setStatus(8);
                wmNewsService.updateById(wmNews);
                sendDelayMeg(wmNews);
            } else {
                publishArticle(wmNews);
            }
            System.err.println(Thread.currentThread().getName() + "执行审核结束。。。");
        }

    }

    /*
        发送延时队列
     */
    @Autowired
    RedissonClient client;
    private void sendDelayMeg(WmNews wmNews) {
        //设置未发布状态
        wmNews.setStatus(8);
        wmNewsService.updateById(wmNews);
        //获取一个阻塞队列  指定队列名称
        RBlockingQueue<String> blockingQueue = client.getBlockingQueue("article_publish");
        //创建一个延时队列  指定使用哪个阻塞队列
        RDelayedQueue<String> delayedQueue = client.getDelayedQueue(blockingQueue);

        //发送延迟消息  指定消息内容  延迟时间  时间单位
        Long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
        delayedQueue.offer(JSON.toJSONString(wmNews), time, TimeUnit.MILLISECONDS);
        System.out.println("消息发送完成" + new Date());
    }

    /*
        自管理敏感词审核
     */
    @Autowired
    IWmSensitiveService sensitiveService;
    private boolean checkSelf(WmNews wmNews, String text) {
        //第一步  使用工具类  初始化
        if(SensitiveWordUtil.dictionaryMap.size() == 0){
            //从数据库查询
            LambdaQueryWrapper<WmSensitive> query = new LambdaQueryWrapper<>();
            query.select(WmSensitive::getSensitives);
            List<String> words = sensitiveService.listObjs(query, o -> o.toString());
            //初始化map
            SensitiveWordUtil.initMap(words);
        }
        //匹配文本内容
        String content = wmNews.getTitle() + wmNews.getLabels() + text;
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        //判断结果
        if (map.size() > 0){
            wmNews.setStatus(2);
            //审核不通过的原因
            Set<String> keys = map.keySet();
            String label = String.join(",", keys);
            wmNews.setReason("自管理敏感词审核不通过" + label);
            wmNewsService.updateById(wmNews);
            return false;
        }else {
            return true;
        }
    }

    /*
        发布文章
     */
    private void publishArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        //设置文章数据
        BeanUtils.copyProperties(wmNews,dto);
        dto.setId(null);
        //获取作者id 查询用户
        WmUser wmUser = userService.getById(wmNews.getUserId());
        dto.setAuthorId(wmUser.getApAuthorId());
        dto.setAuthorName(wmUser.getName());

        //频道信息
        WmChannel channel = channelService.getById(wmNews.getChannelId());
        dto.setChannelName(channel.getName());
        dto.setLayout(wmNews.getType());
        dto.setFlag(0);
        //前端显示
        //封面图片转换
        List<ImageDto> coverImages = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        ArrayList<String> list = new ArrayList<>();
        for (ImageDto coverImage : coverImages) {
            list.add(coverImage.getUrl());
        }
        //将集合转变为字符串  用逗号分割
        String join = String.join(",", list);
        dto.setImages(join);

        //远程调用
        ResponseResult<Long> responseResult = articleFeign.saveArticle(dto);
        //判断结果
        if (responseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())){
            Long articleId = responseResult.getData();
                //文章id写入自媒体文章表中
                wmNews.setArticleId(articleId);
                //修改文章表状态
                wmNews.setStatus(9);
                wmNewsService.updateById(wmNews);
        }
    }

    /*
        图片审核
     */

    private boolean checkImages(WmNews wmNews, List<String> images) {
        boolean flag = false;
        if (images.size() == 0){
            //无图模式
            return flag = true;
        }
        try {
            List<byte[]> list = new ArrayList<>();
            //minio服务部署在内网  所以要先下载再进行图片审核
            for (String image : images) {
                if (!StringUtils.isEmpty(image)){
                    InputStream inputStream = minIOService.download(image);
                    //转成字节数组
                    byte[] imagesBytes = IOUtils.toByteArray(inputStream);
                    list.add(imagesBytes);
                }
            }
            Map map = imageScan.imageScan(list);
            //获取结果
            String result = (String) map.get("suggestion");
            switch (result){
                case "pass":
                    flag = true;
                    break;
                case "block":
                    //审核不通过
                    wmNews.setStatus(2);
                    //审核不通过的原因
                    wmNews.setReason((String) map.get("label"));
                    wmNewsService.updateById(wmNews);
                    break;
                case "review":
                    //人工审核
                    wmNews.setStatus(3);
                    wmNewsService.updateById(wmNews);
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /*
        判断是否为文本信息
     */

    private boolean checkText(WmNews wmNews, String text) {
        boolean result = false;
        // 需要审核的文本包含 标题+标签+文本内容
//        text = wmNews.getTitle() + wmNews.getLabels() + wmNews.getContent();
        text = wmNews.getTitle() + wmNews.getLabels() + text;
//        System.err.println(text);
        try {
            Map map = textScan.greenTextScan(text);
            // 判断结果
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass":
                    result = true;
                    break;
                case "block":
                    // 审核不通过
                    // 修改文章状态为 2
                    wmNews.setStatus(2);
                    // 记录对应的原因
                    wmNews.setReason("阿里云文本审核失败: " + map.get("label"));
                    wmNewsService.updateById(wmNews);
                    break;
                case "review":
                    // 需要人工审核
                    // 修改文章状态为 3
                    wmNews.setStatus(3);
                    wmNewsService.updateById(wmNews);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /*
        从文章内容中提取文本内容和图片内容
     */
    private Map<String, Object> getTextAndImages(String content) {
        HashMap<String, Object> map = new HashMap<>();
        StringBuilder builder = new StringBuilder();
        ArrayList<String> images = new ArrayList<>();
        List<ContentDto> contentDtos = JSON.parseArray(content, ContentDto.class);
        for (ContentDto dto : contentDtos) {
            //判断是文本还是图片
            if (dto.getType().equals("text")){
                //文本信息  保存在文本中
                builder.append(dto.getValue());
            }else {
                //图片信息  保存在图片集合中
                images.add(dto.getValue());
            }
        }

         map.put("text",builder.toString());
         map.put("images",images);
        return map;
    }
}
